#include "EjectDLL.h"

EjectDLL::EjectDLL(QObject *parent)
    : QObject(parent), QRunnable(), cond(new QWaitCondition), mutex(new QMutex)
{
}

void EjectDLL::Eject_init(DWORD pid, const QString &DllPath)
{
    this->pid = pid;
    this->dllPath = DllPath;
}

void EjectDLL::run()
{
    mutex->lock();
    // 创建模块快照
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    if (hSnapshot == INVALID_HANDLE_VALUE)
    {
        emit SendDra("创建工具帮助快照失败！");
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    MODULEENTRY32 moduleEntry = {0};
    moduleEntry.dwSize = sizeof(MODULEENTRY32);
    bool found = false;

    // 遍历模块查找目标 DLL
    if (Module32First(hSnapshot, &moduleEntry))
    {
        do
        {
            if (strcmp(moduleEntry.szModule, dllPath.toStdString().c_str()) == 0)
			{
				found = true;
				break;
			}
        } while (Module32Next(hSnapshot, &moduleEntry));
    }
    CloseHandle(hSnapshot);

    if (!found)
    {
        emit SendDra("未找到模块: " + dllPath);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    // 打开目标进程
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess)
    {
        emit SendDra("无法打开目标进程 ID: " + QString::number(pid));
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    // 获取 FreeLibrary 地址
    HMODULE hKernel32 = LoadLibrary(TEXT("kernel32"));
    FARPROC lpFreeLibrary = GetProcAddress(hKernel32, "FreeLibrary");
    if (!lpFreeLibrary)
    {
        emit SendDra("无法获取 FreeLibrary 的地址");
        CloseHandle(hProcess);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    // 创建远程线程以调用 FreeLibrary
    HANDLE hThread = CreateRemoteThread(hProcess, nullptr, 0,
                                        reinterpret_cast<LPTHREAD_START_ROUTINE>(lpFreeLibrary),
                                        moduleEntry.modBaseAddr, 0, nullptr);
    if (!hThread)
    {
        emit SendDra("创建远程线程失败");
        CloseHandle(hProcess);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    // 等待线程完成
    WaitForSingleObject(hThread, INFINITE);
    emit SendDra("成功卸载 DLL: " + dllPath);

    // 清理资源
    CloseHandle(hThread);
    CloseHandle(hProcess);
    cond->wait(mutex);
    mutex->unlock();
}
